package hust.rpc.serialize.json;

import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.type.TypeFactory;
import hust.rpc.pojo.RpcRequest;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.io.IOException;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;

public class JsonUtils {

    private static final ObjectMapper mapper = new ObjectMapper();
    private static final Logger logger = LogManager.getLogger(JsonUtils.class);

    public static <T> String toJson(T data) {
        String result = null;
        try {
            result = mapper.writer().writeValueAsString(data);
        } catch (IOException e) {
            logger.error("序列化发生异常: ", e);
        }
        return result;
    }

    public static Object fromJson(String json, JavaType javaType) {
        Object o = null;
        try {
            o = mapper.readValue(json, javaType);
        } catch (IOException e) {
            logger.error("反序列化发生异常: ", e);
        }
        return o;
    }

    public static <T> T fromJson(String json, Class<T> clazz) {
        T t = null;
        try {
            t = mapper.readValue(json, clazz);
        } catch (IOException e) {
            logger.error("反序列化发生异常: ", e);
        }
        return t;
    }

    public static JavaType getJavaType(Type type) {
        // 判断是否带有泛型
        if (type instanceof ParameterizedType) {
            Type[] actualTypeArguments = ((ParameterizedType) type).getActualTypeArguments();
            // 获取泛型类型
            Class<?> rowClass = (Class<?>) ((ParameterizedType) type).getRawType();
            JavaType[] javaTypes = new JavaType[actualTypeArguments.length];
            for (int i = 0; i < actualTypeArguments.length; i++) {
                // 泛型也可能带有泛型,递归获取
                javaTypes[i] = getJavaType(actualTypeArguments[i]);
            }
            return TypeFactory.defaultInstance().constructParametricType(rowClass, javaTypes);
        } else {
            // 简单类型直接用该类构建JavaType
            Class<?> clazz = (Class<?>) type;
            return TypeFactory.defaultInstance().constructParametricType(clazz, new JavaType[0]);
        }
    }

    public static Object[] fromJson(Method method, String[] args) {
        Type[] types = method.getGenericParameterTypes();
        // 报错
        if (args.length != types.length) throw new RuntimeException("");
        Object[] results = new Object[args.length];
        for (int i = 0; i < args.length; i++) {
            // 将来可作缓存
            results[i] = fromJson(args[i], getJavaType(types[i]));
        }
        return results;
    }
}
